# 半监督学习实战
import numpy as np
from sklearn import datasets
from sklearn.semi_supervised import LabelSpreading
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn import ensemble
import matplotlib.pyplot as plt

digits = datasets.load_digits()
total = len(digits.data)
indices = np.arange(total)
np.random.RandomState(2).shuffle(indices) # indices变为乱序序列
X = digits.data[indices] # 打乱顺序后的数据样本
y = digits.target[indices] # 打乱顺序后的数据标签

# 构造用于半监督学习的数据集
labeled_points = 40 # 设置有标签数据为前40个样本
y_train = np.copy(y)
y_train[labeled_points:] = -1 #将训练集中40以后得数据标签设为"-1"(去标签)

lp_model = LabelSpreading(gamma=0.25) # 实例化LabelSpreading模型，gamma是超参数
lp_model.fit(X,y_train) # 训练模型
pre_labels = lp_model.transduction_[labeled_points:] # 获取预测结果
true_labels = y[labeled_points:] # 获取真实标签
# 查看模型分类结果报告
print("Label Spreading model:%d labeled & %d unlabeled points (%d total)" % (labeled_points,total - labeled_points,total))
print(classification_report(true_labels,pre_labels)) # 打印性能指标
print(confusion_matrix(true_labels,pre_labels)) # 打印混淆矩阵

error_index = np.where(pre_labels - true_labels != 0)[0]
f = plt.figure(figsize=(7,5)) # 创建画布
f.suptitle("Learning with small amount of labeled data")
for i , index in enumerate(error_index[:10]):
      image = X[index + labeled_points].reshape(8,8)
      sub = f.add_subplot(2,5,i+1) # 通过2行5列的方式展示每个子图
      sub.imshow(image,cmap=plt.cm.gray_r)
      plt.xticks([]) # 不显示横坐标
      plt.yticks([]) # 不显示纵坐标
      sub.set_title("predict: %i\ntrue: %i" % (pre_labels[index],true_labels[index]))
plt.show()

clf = ensemble.ExtraTreesClassifier() # 实例化极限树分类模型
clf = clf.fit(X[:labeled_points],y_train[:labeled_points]) # 训练模型
pred = clf.predict(X[labeled_points:]) # 预测
print(classification_report(y[labeled_points:],pred)) # 打印性能指标
print(confusion_matrix(y[labeled_points:],pred)) # 打印混淆矩阵
